package service

import (
	"common/biz"
	"common/logs"
	"common/utils"
	"context"
	"core/dao"
	"core/models/db"
	"core/models/entity"
	"core/repo"
	"framework/msError"
	"github.com/shopspring/decimal"
	"hall/models/request"
	"hall/models/response"
	"strconv"
)

type GoodsService struct {
	goodsDao  *dao.GoodsDao
	configDao *dao.ConfigDao
	typeDao   *dao.TypeDao
}

func (s *GoodsService) GetList(ctx context.Context, uid uint, req *request.GoodsIDAsPage) (int64, int, []*response.GoodsList) {
	count, list := s.goodsDao.GoodsAll(ctx, req)
	isIOS := s.configDao.GetVal(ctx, "is_ios")
	isIos, _ := strconv.Atoi(isIOS)
	data := make([]*response.GoodsList, 0)
	restrictedPurchase := s.configDao.GetVal(ctx, "restricted_purchase")
	for _, v := range *list {
		donates, goodsPay := s.getDonateOrGoodsPay(v.Donate, v.GoodsPay)
		restrictNum := v.RestrictNum
		if restrictNum < 0 {
			//限购次数
			restrictNum -= s.BuyOrderCount(ctx, uid, v.ID, utils.DecimalStringByInt(restrictedPurchase))
		}

		data = append(data, &response.GoodsList{
			ID:          v.ID,
			TypeID:      v.TypeID,
			TypeName:    v.Types.Name,
			TypeImg:     v.Types.Img,
			Remain:      v.Remain,
			RestrictNum: restrictNum,
			Price:       v.Price,
			Name:        v.Name,
			Img:         v.Img,
			Donate:      donates,
			Pay:         goodsPay,
		})
	}
	return count, isIos, data
}

func (s *GoodsService) CreateOrder(ctx context.Context, order *entity.GoodsOrder) (*response.GoodsList, *entity.GoodsOrder, error) {
	goodsOrder, goods, err := s.goodsDao.GoodsNumSub(ctx, order)
	if err != nil {
		return nil, nil, err
	}
	donates, goodsPay := s.getDonateOrGoodsPay(goods.Donate, goods.GoodsPay)
	restrictNum := goods.RestrictNum
	restrictedPurchase := s.configDao.GetVal(ctx, "restricted_purchase")
	if restrictNum < 0 {
		//限购次数
		restrictNum -= s.BuyOrderCount(ctx, order.UID, goods.ID, utils.DecimalStringByInt(restrictedPurchase))
	}
	goodsMsg := &response.GoodsList{
		ID:          goods.ID,
		TypeID:      goods.TypeID,
		TypeName:    goods.Types.Name,
		TypeImg:     goods.Types.Img,
		Remain:      goods.Remain,
		RestrictNum: restrictNum,
		Price:       goods.Price,
		Name:        goods.Name,
		Img:         goods.Img,
		Donate:      donates,
		Pay:         goodsPay,
	}
	return goodsMsg, goodsOrder, err
}

func (s *GoodsService) GetGoods(ctx context.Context, uid, gid uint) *db.GoodsHasOneType {
	goods := s.goodsDao.GetGoods(ctx, gid)
	restrictNum := goods.RestrictNum
	restrictedPurchase := s.configDao.GetVal(ctx, "restricted_purchase")
	if restrictNum < 0 {
		//限购次数
		restrictNum -= s.BuyOrderCount(ctx, uid, gid, utils.DecimalStringByInt(restrictedPurchase))
	}
	return goods
}

func (s *GoodsService) OrderInfo(ctx context.Context, cancel int, uid uint, gid uint) *entity.GoodsOrder {
	return s.goodsDao.MongoGetOrder(ctx, cancel, uid, gid)
}

func (s *GoodsService) OrderCancel(ctx context.Context, uid uint, code string) (*response.GoodsList, *entity.GoodsOrder, error) {
	order, goods, err := s.goodsDao.GoodsNumAdd(ctx, uid, code)
	if err != nil {
		return nil, nil, err
	}
	restrictedPurchase := s.configDao.GetVal(ctx, "restricted_purchase")
	fpString, _ := decimal.NewFromString(restrictedPurchase)
	fpStringData := fpString.IntPart()
	donates, goodsPay := s.getDonateOrGoodsPay(goods.Donate, goods.GoodsPay)
	restrictNum := goods.RestrictNum
	if restrictNum < 0 {
		//限购次数
		restrictNum -= s.BuyOrderCount(ctx, uid, goods.ID, fpStringData)
	}
	goodsMsg := &response.GoodsList{
		ID:          goods.ID,
		TypeID:      goods.TypeID,
		TypeName:    goods.Types.Name,
		TypeImg:     goods.Types.Img,
		Remain:      goods.Remain,
		RestrictNum: restrictNum,
		Price:       goods.Price,
		Name:        goods.Name,
		Img:         goods.Img,
		Donate:      donates,
		Pay:         goodsPay,
	}
	return goodsMsg, order, err
}

func (s *GoodsService) OrderInfoByOrderNo(ctx context.Context, uid uint, orderNo string) *entity.GoodsOrder {
	return s.goodsDao.MongoGetOrderByOrderNo(ctx, uid, orderNo)
}

func (s *GoodsService) GetOrderList(ctx context.Context, uid uint, req *request.GoodsIDAsPage) (int64, *[]entity.GoodsOrder) {
	count, list := s.goodsDao.OrderAll(ctx, req, uid)
	return count, list
}

func (s *GoodsService) GoodsPay(ctx context.Context, order *entity.GoodsOrder, response string) error {
	return s.goodsDao.OrderPay(ctx, order, response)
}

func (s *GoodsService) TypeInfo(ctx context.Context, id uint) *db.Type {
	return s.typeDao.GetInfo(ctx, id)
}

func (s *GoodsService) OvertimeOrderList(ctx context.Context) *[]entity.GoodsOrder {
	return s.goodsDao.OvertimeOrderList(ctx)
}

func (s *GoodsService) BuyOrderCount(ctx context.Context, uid, gid uint, types int64) int64 {
	return s.goodsDao.BuyOrderCount(ctx, uid, gid, types)
}

func (s *GoodsService) ConfigGetVal(ctx context.Context, name string) string {
	return s.configDao.GetVal(ctx, name)
}

func (s *GoodsService) getDonateOrGoodsPay(donate []db.TypeCardDonateHaxOneTypeOfRole, pay []db.GoodsPayHaxOneType) ([]response.Donate, []response.GoodsPay) {
	donates := make([]response.Donate, 0)
	for _, val := range donate {
		odds := decimal.NewFromFloat(float64(val.Odds))
		odds = odds.Div(decimal.NewFromFloat(100))
		oddsData, _ := odds.Float64()
		if val.Type == 1 {
			donate := response.Donate{
				Type:     val.Type,
				LinkID:   val.LinkID,
				LinkName: val.LinkRole.Name,
				LinkImg:  val.LinkRole.Img,
				Num:      val.Num,
				Odds:     oddsData,
			}
			donates = append(donates, donate)
		} else {
			donate := response.Donate{
				Type:     val.Type,
				LinkID:   val.LinkID,
				LinkName: val.LinkType.Name,
				LinkImg:  val.LinkType.Img,
				Num:      val.Num,
				Odds:     oddsData,
			}
			donates = append(donates, donate)
		}
	}
	goodsPay := make([]response.GoodsPay, 0)
	for _, val := range pay {
		var num = utils.DecimalIntByFloat(val.Num)
		if val.TypeID == 11 {
			num = utils.DecimalIntDiv(val.Num, val.Types.Val)
		}
		pay := response.GoodsPay{
			TypeID:   val.TypeID,
			TypeName: val.Types.Name,
			TypeImg:  val.Types.Img,
			Num:      num,
		}
		goodsPay = append(goodsPay, pay)
	}
	return donates, goodsPay
}

func (s *GoodsService) MongoUpOrderPayMethod(ctx context.Context, orderNo string, method string) error {
	return s.goodsDao.MongoUpOrderPayMethod(ctx, orderNo, method)
}

func (s *GoodsService) IosPayOrder(ctx context.Context, uid uint, orderNo string) *msError.Error {
	order := s.OrderInfoByOrderNo(ctx, uid, orderNo)
	if order == nil || order.OrderNo == "" {
		logs.Error("[Goods]用户%d Pay IosPayOrder err:未获取到苹果支付订单数据 req=%v", uid, order)
		return biz.GoodsOrderError
	}
	if order.GoodsType != 1 {
		logs.Error("[Goods]用户%d Pay IosPayOrder err:订单类型不对 req=%v", uid, order)
		return biz.GoodsOrderError
	}
	err := s.goodsDao.OrderIosPay(ctx, order, "")
	if err != nil {
		logs.Error("[Goods]用户%d Pay GoodsIosPay err:苹果支付处理失败 req=%v,payErr=%v", uid, order, err)
		return biz.GoodsPointsError
	}
	return nil
}

func NewGoodsService(r *repo.Manager) *GoodsService {
	return &GoodsService{
		goodsDao:  dao.NewGoodsDao(r),
		typeDao:   dao.NewTypeDao(r),
		configDao: dao.NewConfigDao(r),
	}
}
